import os
from pathlib import Path
from typing import Literal

from pydantic import computed_field, field_validator
from pydantic_core import MultiHostUrl
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        # Use top level .env file (one level above ./app/)
        env_file=".env",
        env_file_encoding="utf-8",
        env_ignore_empty=True,
        extra="ignore",
    )

    # project settings
    PROJECT_NAME: str = Path.cwd().name
    VERSION: str = "1.0.0"
    DESCRIPTION: str = "项目描述"
    ENVIRONMENT: Literal["local", "staging", "production"] = "local"
    CONTEXT_PATH: str = "/api"

    # server settings
    SERVER_APP: str = "main:app"
    SERVER_HOST: str = "127.0.0.1"
    SERVER_PORT: int = 8080
    SERVER_LOG_CONFIG: str | None = None
    SERVER_RELOAD: bool = False
    SERVER_WORKERS: int = 1
    SERVER_TIMEOUT_KEEP_ALIVE: int = 5

    # database settings
    DB_SERVER: str
    DB_PORT: int
    DB_DB: str
    DB_USER: str
    DB_PASSWORD: str
    DB_ECHO: bool = False
    DB_POOL_SIZE: int = 10
    DB_MAX_OVERFLOW: int = 10
    DB_POOL_RECYCLE: int = 3600
    DB_POOL_PRE_PING: bool = True

    # logging settings
    LOG_LEVEL: Literal["TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"] = "INFO"
    LOG_DIR: str | None = None

    # thread settings
    MAX_THREADS_LIMIT: int = 200

    @computed_field
    @property
    def SQLALCHEMY_DATABASE_URI(self) -> str:
        return str(
            MultiHostUrl.build(
                scheme="mysql+pymysql",
                host=self.DB_SERVER,
                port=self.DB_PORT,
                path=self.DB_DB,
                username=self.DB_USER,
                password=self.DB_PASSWORD,
            )  # 示例：mysql+pymysql://root:123456@127.0.0.1:3306/fastapi_web
        )

    # 使用自定义验证器调整值。通过mode指定验证是在字段验证前还是验证后进行
    # @see https://docs.pydantic.dev/2.0/usage/validators/
    @field_validator("CONTEXT_PATH", mode="before")
    def decode_context_path(cls, v: str) -> str:
        return v.rstrip("/") if v.endswith("/") else v


settings = Settings()  # type: ignore
